﻿using System;
using System.Diagnostics;
using System.Diagnostics.Contracts;

namespace Postnuclear
  {
  /// <summary>
  /// Represents a value which can be changed and observed.
  /// </summary>
  /// <typeparam name="TValue">The type of the value.</typeparam>
  public sealed class ObservableValue<TValue>
    : IValueProvider<TValue>
    {
    #region Public

    // Constructors

    /// <summary>
    /// Initializes a new instance of the <see cref="ObservableValue{TValue}"/> class.
    /// </summary>
    /// <param name="value">The observed value.</param>
    public ObservableValue(TValue value)
      {
      Contract.Ensures(object.Equals(Value, value));

      Value = value;
      }

    // Events

    /// <summary>
    /// Occurs when <see cref="Value"/> changes.
    /// </summary>
    public event EventHandler<EventArgs> ValueChanged;

    // Properties

    /// <summary>
    /// Gets or sets the value.
    /// </summary>
    public TValue Value
      {
      get
        {
        return _value;
        }

      set
        {
        if (object.Equals(value, _value))
          {
          return;
          }

        _value = value;
        ValueChanged.Raise(this);
        }
      }

    #endregion

    #region Private

    // Fields

    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    private TValue _value;

    #endregion
    }
  }
